home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Game Programming for Dummies (2nd Edition)
/
WinGamProgFD.iso
/
mac
/
DirectX SDK
/
DXSDK
/
samples
/
Multimedia
/
DirectMusic
/
PlayAudio
/
readme.txt
< prev
next >
Wrap
Text File
|
2001-10-10
|
7KB
|
136 lines
//-----------------------------------------------------------------------------
//
// Sample Name: PlayAudio Sample
//
// Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
//
// GM/GS« Sound Set Copyright ⌐1996, Roland Corporation U.S.
//
//-----------------------------------------------------------------------------
Description
===========
The PlayAudio sample shows how to load a segment and play it on an
audiopath, how to use DirectMusic notifications, and how to change
global performance parameters.
Path
====
Source: DXSDK\Samples\Multimedia\DirectMusic\PlayAudio
Executable: DXSDK\Samples\Multimedia\DirectMusic\Bin
User's Guide
============
Play the default segment, or load another wave, MIDI, or DirectMusic
Producer segment file by clicking Segment File. Adjust the tempo and
volume by using the sliders
Programming Notes
=================
This and other DirectMusic samples uses the DirectMusic sample
framework, CMusicManager and CMusicSegment to help encapsulate some of
the common functionality of DirectMusic. The framework is contained
in dmutil.cpp.
This is how the sample works:
* Upon WM_INITDIALOG. See OnInitDialog()
1. Create a Win32 event, g_hDMusicMessageEvent. This will be
used by DirectMusic to signal the app whenever a DirectMusic
notification comes in.
2. Create a help class CMusicManager called g_pMusicManager.
3. Initialize the CMusicManager class. This does the following.
See CMusicManager::Initialize() in dmutil.cpp
- Creates a IDirectMusicLoader8 using CoCreateInstance
- Creates a IDirectMusicPerformance8 using CoCreateInstance
- Calls IDirectMusicPerformance8::InitAudio to init DirectMusic
using a standard audio path.
4. Call IDirectMusicPerformance8::AddNotificationType() passing in
GUID_NOTIFICATION_SEGMENT. This will make DirectMusic tell us about any
segment notifications that come in. This is needed to by this
sample to know when the segment has ended. However DirectMusic
games may not care when the segment has ended.
5. Call IDirectMusicPerformance8::SetNotificationHandle() passing
in the Win32 event, g_hDMusicMessageEvent. This tells DirectMusic
to signal this event when a notification is available.
* Setting up the app message loop. See WinMain()
1. Create the dialog using CreateDialog().
2. In a loop call MsgWaitForMultipleObjects() passing in
g_hDMusicMessageEvent. This will tell us when g_hDMusicMessageEvent
is signaled. Above we have told DirectMusic to signal this event
whenever a DirectMusic notification has come in.
3. If WAIT_OBJECT_0 is returned, then call ProcessDirectMusicMessages(),
See below for details.
4. If WAIT_OBJECT_0 + 1 is returned, then Windows msgs are available, so
do standard msg processing using PeekMessage().
* When "Open File" is clicked. See OnOpenSoundFile()
1. Get the file name from using GetOpenFileName().
2. Release the any old g_pMusicSegment.
3. Call CMusicManager::CollectGarbage(). See dmutil.cpp.
This calls IDirectMusicLoader8::CollectGarbage which
collects any garbage from any old segment that was present.
This is done because some sophisticated segments, in particular
ones that include segment trigger tracks or script tracks, may
have a cyclic reference. For example, a segment trigger that
references another segment that references the first segment, also
via a segment trigger track.
4. Call CMusicManager::SetSearchDirectory(). See dmutil.cpp
This calls IDirectMusicLoader8::SetSearchDirectory()
passing in the GUID_DirectMusicAllTypes and a directory.
This will tell DirectMusic where to look for files that
are referenced inside of segments.
5. Call CMusicManager::CreateSegmentFromFile() to create a
CMusicSegment called g_pMusicSegment from the file.
See dmutil.cpp. This does the following:
- Calls IDirectMusicLoader8::LoadObjectFromFile() to
load the IDirectMusicSegment8 into pSegment.
- Creates CMusicSegment passing in pSegment.
- If the file is a pure MIDI file then it calls
IDirectMusicSegment8::SetParam passing in
GUID_StandardMIDIFile to DirectMusic this. This makes
sure that patch changes are handled correctly.
- If requested, it calls IDirectMusicSegment8::Download()
this will download the segment's bands to the synthesizer.
Some apps may want to wait before calling this to because
the download allocates memory for the instruments. The
more instruments currently downloaded, the more memory
is in use by the synthesizer.
* When "Play" is clicked. See OnPlayAudio()
1. If the UI says the sound should be looped, then call
CMusicSegment::SetRepeats passing in DMUS_SEG_REPEAT_INFINITE,
otherwise call CMusicSegment::SetRepeats passing in 0.
2. Call CMusicSegment::Play() which calls
IDirectMusicPerformance8::PlaySegmentEx(). See dmutil.cpp.
* Upon a DirectMusic notification. See ProcessDirectMusicMessages().
This sample wants to know if the primary segment has stopped playing
so it can updated the UI so tell the user that they can play
the sound again. This is rather complex, but typically apps
will not need this functionality. Here is what has to be done:
1. Call IDirectMusicPerformance8::GetNotificationPMsg() in a loop
to process each PMsg that has occurred.
2. Switch off the pPMsg->dwNotificationOption. This sample
only handles it if its a DMUS_NOTIFICATION_SEGEND. This tells
us that segment has ended.
3. Call QueryInterface on the pPMsg->punkUser, quering for a
IDirectMusicSegmentState8.
4. Using the IDirectMusicSegmentState8, call GetSegment to
get a IDirectMusicSegment* of the segment it refers to.
This call may fail is the segment may have gone away before this
notification was handled.
5. Call QueryInterface IDirectMusicSegment to get a IDirectMusicSegment8
6. Compare this pointer to the IDirectMusicSegment8 pointer
in g_pMusicSegment, to see if this was the primary segment.
This may not always be the case since segments can have segments enbedded
inside of them, we only want handle when the primary segment has
stopped playing. If it has, then update the UI
7. Cleanup all the interfaces.